<template>
  <!-- 内容区域 -->
  <div
    :style="{
      backgroundImage:
        'url(' + voteInfo.appBizVoteLayout?.bannerBackground + ')',
    }"
    class="vote_page"
  >
    <div class="vote_content">
      <!-- 轮播图 -->
      <Swipe :autoplay="3000" class="my-swipe" lazy-render>
        <SwipeItem v-for="image in voteInfo.appBizVote.bannerUrls" :key="image">
          <VanImage
            :height="isMobile ? '14rem' : '350px'"
            :src="image"
            fit="cover"
            lazy-load
            width="100%"
          />
        </SwipeItem>
      </Swipe>
      <!-- 标题和统计 -->
      <div class="statistical_table p15">
        <h2 class="f17 fw500">
          {{ statisticalData.voteName }}
        </h2>
        <div class="statistical_row mt08" @click="showVConsole">
          <Row class="mt05">
            <Col span="8">
              <h2 class="f24 fw500">
                {{ statisticalData.totalVoteUv || 0 }}
              </h2>
              <p class="mt05">参与人数</p>
            </Col>
            <Col span="8">
              <h2 class="f24 fw500">
                {{ statisticalData.totalVoteNum || 0 }}
              </h2>
              <p class="mt05">投票数</p>
            </Col>
            <Col span="8">
              <h2 class="f24 fw500">
                {{ statisticalData.totalViewNum || 0 }}
              </h2>
              <p class="mt05">访问量</p>
            </Col>
          </Row>
          <div class="time_down f12">
            <img alt="" src="../../assets/images/clock.svg" />
            距离投票结束还有
            <CountDown
              :time="statisticalData.endDateTimeStamp - new Date().getTime()"
              format="DD 天 HH 时 mm 分"
            />
          </div>
        </div>
      </div>
      <!-- 搜索 -->
      <div class="pc_search">
        <Search
          v-model="params.candidateName"
          class="vote_search"
          placeholder="搜索"
          @cancel="onSearch"
          @search="onSearch"
        />
        <div v-if="!isMobile" class="pc_nav">
          <van-button
            v-if="voteInfo.appBizVoteSetting.voteType === 'normal'"
            class="mr15"
            @click="openDialog('VoteRanking')" 
          >
            排行榜
          </van-button>
          <van-button class="mr15" @click="openDialog('VoteDetail')">
            活动规则
          </van-button>
          <van-button class="mr15" @click="openDialog('VoteEnroll')">
            个人中心
          </van-button>
        </div>
      </div>
      <!-- 候选项分组 -->
      <Tabs
        v-if="voteInfo.appBizVote.isGroup === 'Y'"
        v-model:active="params.voteGroupId"
        class="tab_label mt08"
        @click-tab="onClickTab"
      >
        <Tab
          v-for="item in groupList"
          :key="item.voteGroupId"
          :name="item.voteGroupId"
          :title="item.groupName"
        />
      </Tabs>
      <!-- 候选项 -->
      <div class="mr15 ml15">
        <p class="vote_rule">
          {{ voteTip }}
        </p>
        <List
          v-model:loading="loading"
          :finished="finished"
          :immediate-check="false"
          finished-text="没有更多了"
          @load="onLoadMore"
        >
          <div class="vote_list">
            <VoteOption
              v-for="item in list"
              :key="item.candidateId"
              :vote-item="item"
              @handle-submit="voteSubmit"
            />
          </div>
        </List>
        <p v-if="!isMobile && !finished" class="pc_more" @click="onLoadMore">
          加载更多
        </p>
      </div>
      <BackTop bottom="12rem" target=".vote_content" />
    </div>
    <!-- 选择投票 -->
    <VoteSubmit
      :check-group="checkGroup"
      :vote-info="voteInfo"
      @handle-submit="voteSubmit"
    />
  </div>
  <!-- 菜单切换 -->
  <VoteNav v-if="isMobile" />
  <!-- 不能访问的提示 -->
  <Popup
    v-model:show="showPopup"
    :close-on-click-overlay="false"
    :overlay-style="{ background: '#fff' }"
    round
  >
    <Empty :description="errorMsg" class="empty t-center" image-size="100" />
  </Popup>
  <!-- pc弹窗展示 -->
  <ElDialog v-model="dialogVisible" :title="pcDialogTitle" width="600px">
    <component :is="components[dialogComponent]" />
  </ElDialog>
</template>

<script setup>
import { apiCheckToken } from "@/server/business/survey.js";
import {
  getGeneralinfo,
  getList,
  getVoteinfo,
  updateViewNum
} from "@/server/business/vote.js";
import { commonStore } from "@/stores/common.js";
import { setWeappToken } from "@/utils/auth.js";
import { getUrlQuery, showVConsole } from "@/utils/common.js";
import { ElDialog } from "element-plus";
import { storeToRefs } from "pinia";
import {
  BackTop,
  closeToast,
  Col,
  CountDown,
  Empty,
  Image as VanImage,
  List,
  Popup,
  Row,
  Search,
  showLoadingToast,
  showNotify,
  Swipe,
  SwipeItem,
  Tab,
  Tabs
} from "vant";
import { computed, reactive, ref } from "vue";
import { useRoute } from "vue-router";
import { handleSubmit } from "./components/control.js";
import { store } from "./components/store.js";
import VoteNav from "./components/voteNav.vue";
import VoteOption from "./components/voteOption.vue";
import VoteSubmit from "./components/voteSubmit.vue";
import voteDetail from "./vote-detail.vue";
import voteEnroll from "./vote-enroll.vue";
import ranking from "./vote-ranking.vue";

const commonStores = commonStore();
const { isMobile } = storeToRefs(commonStores);
const useQuery = getUrlQuery(); // href获取数据
const route = useRoute();
const statisticalData = ref({});
const groupList = ref([]);
const list = ref([]);
const voteInfo = ref(store.voteInfo);
const userInfo = ref(store.userInfo);
const loading = ref(false);
const finished = ref(false);
const checkGroup = ref({});
const showPopup = ref(false);
const errorMsg = ref();
const dialogVisible = ref(false);
const dialogComponent = ref();
const components = ref({
  VoteRanking: ranking, VoteDetail: voteDetail, VoteEnroll: voteEnroll
});
const params = reactive({
  pageNum: 1,
  pageSize: 12,
  sortType: "",
  candidateName: "",
  voteGroupId: "",
  voteId: route.query.id
  // candidateFirm: null,
  // orgName: null
});
// 投票规则 提示
const voteTip = computed(() => {
  if (
    voteInfo.value.appBizVoteSetting?.isGroupRule === "Y" &&
    params.voteGroupId
  ) {
    // 启用分组投票规则 且 已切换到分组
    if (
      voteInfo.value.appBizVoteSetting?.voteType === "normal" &&
      checkGroup.value.minVote &&
      checkGroup.value.maxVote
    ) {return `请选择 ${checkGroup.value.minVote} ~ ${checkGroup.value.maxVote} 个进行投票`;}
    else if (voteInfo.value.appBizVoteSetting?.voteType === "decision") {
      return `${
        checkGroup.value.agreeMinVote && checkGroup.value.agreeMaxVote
          ? "请选择" +
          checkGroup.value.agreeMinVote +
          " ~ " +
          checkGroup.value.agreeMaxVote +
          "赞成票，"
          : ""
      } ${
        checkGroup.value.againstMinVote && checkGroup.value.againstMaxVote
          ? checkGroup.value.againstMinVote +
          " ~ " +
          checkGroup.value.againstMaxVote +
          "反对票"
          : ""
      }`;
      }
    return "";
  } else {
    // 不启用分组投票规则 或 在全部分组下
    if (
      voteInfo.value.appBizVoteSetting?.voteType === "normal" &&
      voteInfo.value.appBizVoteSetting.votesPerson
    ){
      return `每个用户可投 ${voteInfo.value.appBizVoteSetting.votesPerson} ${
        voteInfo.value.appBizVoteLayout.candidateTitleUnit || ""
      }`;}
    else if (
      voteInfo.value.appBizVoteSetting?.voteType === "decision" &&
      (voteInfo.value.appBizVoteSetting.agreeVote ||
        voteInfo.value.appBizVoteSetting.againstVote)
    ){
      return `每个用户可投 ${
        voteInfo.value.appBizVoteSetting.agreeVote || ""
      } 赞成票，${voteInfo.value.appBizVoteSetting.againstVote || ""} 反对票`;
      }
    else return "";
  }
});
// pc弹框标题
const pcDialogTitle = computed(() => {
  let obj = {
    VoteRanking: "排行", VoteDetail: "活动规则", VoteEnroll: "个人中心"
  };
  return obj[dialogComponent.value];
});
const onLoadMore = () => {
  getSurveyList()
  params.pageNum++;
}
// 搜索候选项
const onSearch = () => {
  params.pageNum = 1;
  list.value = [];
  getSurveyList();
};
// 获取候选项列表
const getSurveyList = () => {
  getList(params).then((res) => {
    list.value.push(...res.rows);
    loading.value = false; // 加载状态结束
    finished.value = list.value.length >= res.total; // true 数据全部加载完成
  });
};
// 投票操作
const voteSubmit = () => {
  handleSubmit(async () => {
    const res = await getGeneralinfo({ voteId: route.query.id })
    statisticalData.value = res.data;
    onClickTab();
  });
};
// 切换分组
const onClickTab = () => {
  list.value = [];
  loading.value = true;
  params.pageNum = 1;
  getSurveyList();
  checkGroup.value = groupList.value.filter(i => i.voteGroupId === params.voteGroupId)[0];
};
// 获取登录者信息
const getUserInfo = async () => {
  if (!useQuery.token || ["#token%23", "#token#"].includes(useQuery.token)) {
    return (localStorage.userInfo = "");
  }
  setWeappToken(useQuery.token);
  let res = await apiCheckToken({ memberUserToken: useQuery.token });
  localStorage.userInfo = JSON.stringify(res.data);
  for (let key in res.data) {
    userInfo.value[key] = res.data[key];
  }
};
// pc弹框查看
const openDialog = (routeName) => {
  dialogVisible.value = true;
  dialogComponent.value = routeName;
};
// 校验合集
const checks = {
  // 仅注册用户
  register: () => {
    if (userInfo.value.contactPhone) {
      checks.isTime(
        new Date(userInfo.value.logonTime).getTime(),
        `仅限${voteInfo.value.appBizVotePublish.joinDateStart}~${voteInfo.value.appBizVotePublish.joinDateEnd}时间注册的用户可以投票`
      );
    } else {
      checks.errorMsg("注册用户才可以访问");
    }
  },
  //仅实名职工 realName
  realName: () => {
    if (userInfo.value.name) {
      checks.isTime(
        new Date(userInfo.value.realNameTime).getTime(),
        `仅限${voteInfo.value.appBizVotePublish.joinDateStart}~${voteInfo.value.appBizVotePublish.joinDateEnd}时间实名的用户可以投票`
      );
    } else {
      checks.errorMsg("实名用户才可以访问");
    }
  },
  //仅工会会员
  member: () => {
    if (userInfo.value.districtTradeUnionName) {
      checks.isTime(
        new Date(userInfo.value.membershipTime).getTime(),
        `仅限${voteInfo.value.appBizVotePublish.joinDateStart}~${voteInfo.value.appBizVotePublish.joinDateEnd}时间加入工会的会员可以投票`
      );
    } else {
      checks.errorMsg("工会会员才可以访问");
    }
  },
  // 时间限制条件
  isTime: (time, errMsg) => {
    if (voteInfo.value.appBizVotePublish.isJoinTime === "Y") {
      let startTime = new Date(
        voteInfo.value.appBizVotePublish.joinDateStart
      ).getTime();
      let endTime = new Date(
        voteInfo.value.appBizVotePublish.joinDateEnd
      ).getTime();
      if (time < startTime || time > endTime) {
        checks.errorMsg(errMsg);
      }
    }
  },
  // 校验是否进入投票时间
  checkVoteTime: () => {
    let time = new Date().getTime();
    let startTime = new Date(voteInfo.value.appBizVote.startDateTime).getTime();
    let endTime = new Date(voteInfo.value.appBizVote.endDateTime).getTime();
    if (time > endTime) checks.errorMsg("投票已结束");
    if (time < startTime) checks.errorMsg("投票未开始");
  },
  // 错误提示
  errorMsg: (msg) => {
    showPopup.value = true;
    errorMsg.value = msg;
  }
};
// 是否可以访问校验
const checkAccess = () => {
  if (voteInfo.value.appBizVotePublish.voteTo === "member") {
    try {
      voteInfo.value.appBizVotePublish.memberRange &&
      checks[voteInfo.value.appBizVotePublish.memberRange]();
    } catch (e) {
      console.error(e);
    }
  }
};
// 获取 投票信息
const getVoteContent = async () => {
  let info = await getVoteinfo({ voteId: route.query.id });
  for (let key in info.data) {
    voteInfo.value[key] = info.data[key] || {};
    localStorage[key] = JSON.stringify(info.data[key] || {});
    if (!info.data.appBizVoteGroup) {
      voteInfo.value.appBizVoteGroup = [];
      localStorage.appBizVoteGroup = JSON.stringify([]);
    }
  }
  groupList.value = [
    { voteGroupId: "", groupName: "全部" },
    ...(info.data.appBizVoteGroup || [])
  ]; // 分组信息
  params.sortType = voteInfo.value.appBizVoteLayout.candidateOrder;
  checks.checkVoteTime(); // 校验是否进入投票时间
};
// 初始化
const init = async () => {
  if (!route.query.id) {
    return showNotify({ type: "danger", message: "缺少投票id" });
  }
  showLoadingToast({ message: "加载中...", forbidClick: true, duration: 0 });
  await getVoteContent();
  await getUserInfo();
  getSurveyList();
  // 投票统计
  const res = await getGeneralinfo({ voteId: route.query.id })
  statisticalData.value = res.data;
  // 更新浏览次数
  if (route.query.pageType !== 'view') {
    await updateViewNum({ voteId: route.query.id });
    if (route.query.type !== 'pc' && voteInfo.value.appBizVotePublish.voteTo !== "all") {
      checkAccess(); // 预览不检测
    }
  }
  closeToast();
};

init();
</script>
<style scoped>
.my-swipe :deep(.van-swipe-item) {
  height: 14rem;
}

.my-swipe :deep(.van-swipe-item img) {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.statistical_table {
  text-align: center;
}

.statistical_row {
  border: 1px solid var(--van-gray-3);
  padding: 0.8rem;
  border-radius: 0.4rem;
  background: rgba(255, 255, 255, 0.2);
}

.time_down {
  background: #e5f1ff;
  border-radius: 2px;
  color: var(--van-blue);
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 2rem 0.8rem 0;
  height: 2.5rem;
  font-size: 1.2rem;
}

.time_down img {
  fill: var(--van-blue);
}

.time_down :deep(.van-count-down) {
  color: var(--van-blue);
  font-size: 1.2rem;
}

.time_down > span {
  line-height: 2rem;
}

.vote_search {
  padding: 0 1.5rem;
  background: none;
}

.vote_search :deep(.van-search__content) {
  background: rgba(227, 228, 230, 0.3);
}

.vote_rule {
  font-size: 1.3rem;
  line-height: 3rem;
  color: #666666;
}

.vote_list {
  display: flex;
  flex-wrap: wrap;
}

.vote_page {
  background-position: center top;
  background-size: cover;
  background-attachment: fixed;
}

.tab_label :deep(.van-tabs__nav) {
  background: none;
}

.pc_search {
  display: flex;
}

.vote_search {
  flex: 1;
}

.pc_more {
  text-align: center;
  cursor: pointer;
  line-height: 40px;
}
</style>
